/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.sais.noisylibrary.core;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.sais.noisylibrary.card.AttributeCard;
import org.sais.noisylibrary.card.Card;
import org.sais.noisylibrary.card.HelperCard;
import org.sais.noisylibrary.card.SituationCard;
import org.sais.noisylibrary.card.SpellCard;

/**
 *
 * @author Romulus
 */
public class GameCore {

    private static ArrayList<Card> sPackage = new ArrayList<Card>();

    static {
        try {
            BufferedReader in = new BufferedReader(new ReadInnerFile("carddatabase.txt").stream);
            for (String line = in.readLine(); line != null; line = in.readLine()) {
                String[] s = line.split("/");
                int type = Integer.parseInt(s[0]);
                for (int i = 0; i < Integer.parseInt(s[2]); ++i) {
                    Card card = null;
                    switch (type) {
                        case 0:
                            card = new AttributeCard(s);
                            break;
                        case 1:
                            card = new SpellCard(s);
                            break;
                        case 2:
                            card = new HelperCard(s);
                            break;
                        case 3:
                            card = new SituationCard(s);
                            break;
                    }
                    if (card != null) {
                        sPackage.add(card);
                    }
                }
            }
            in.close();
        } catch (IOException ex) {
            Logger.getLogger(GameCore.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    private ArrayList<Player> mPlayers = new ArrayList<Player>();
    private ArrayList<AttributeCard> mAttrLib = new ArrayList<AttributeCard>();
    private ArrayList<SpellCard> mSpellLib = new ArrayList<SpellCard>();
    private ArrayList<HelperCard> mHelperLib = new ArrayList<HelperCard>();
    private ArrayList<SituationCard> mSituationLib = new ArrayList<SituationCard>();
    private HashSet<SpellCard> mSpellField = new HashSet<SpellCard>();
    private HashSet<AttributeCard> mAttributeField = new HashSet<AttributeCard>();
    private HashSet<SpellCard> mSpellConsumed = new HashSet<SpellCard>();
    private HashSet<AttributeCard> mAttrConsumed = new HashSet<AttributeCard>();
    private HashSet<HelperCard> mHelperConsumed = new HashSet<HelperCard>();
    private SituationCard mSituationCard = null;
    private boolean mGameStarted = false;
    private int mTurn = 0;

    public GameCore() {
        Collections.shuffle(sPackage);
        for (Card c : sPackage) {
            if (c instanceof AttributeCard) {
                mAttrLib.add((AttributeCard) c);
                continue;
            }
            if (c instanceof SpellCard) {
                mSpellLib.add((SpellCard) c);
                continue;
            }
            if (c instanceof HelperCard) {
                mHelperLib.add((HelperCard) c);
                continue;
            }
            if (c instanceof SituationCard) {
                mSituationLib.add((SituationCard) c);
                continue;
            }
        }
    }

    public void participate(String name) {
        mPlayers.add(new Player(name));
    }

    public boolean isGameStarted() {
        return mGameStarted;
    }

    public void decideOrder() {
        mGameStarted = true;
        Collections.shuffle(mPlayers);
    }

    public void dealInitialHand() {
        for (Player p : mPlayers) {
            for (int i = 0; i < 3; ++i) {
                p.gainAttrCard(drawAttribute());
            }
        }
    }

    public ArrayList<Player> getPlayers() {
        return mPlayers;
    }

    public void dealInitialField() {
        for (int i = 0; i < 5; ++i) {
            mAttributeField.add(drawAttribute());
        }
        for (int i = 0; i < 4; ++i) {
            mSpellField.add(drawSpell());
        }
    }

    private AttributeCard drawAttribute() {
        if (mAttrLib.size() == 0) {
            mAttrLib.addAll(mAttrConsumed);
            mAttrConsumed.clear();
            Collections.shuffle(mAttrLib);
        }
        return mAttrLib.remove(0);
    }

    private SpellCard drawSpell() {
        if (mSpellLib.size() == 0) {
            mSpellLib.addAll(mSpellConsumed);
            mSpellConsumed.clear();
            Collections.shuffle(mSpellLib);
        }
        return mSpellLib.remove(0);
    }

    private HelperCard drawHelperCard() {
        if (mHelperLib.size() == 0) {
            mHelperLib.addAll(mHelperConsumed);
            mHelperConsumed.clear();
            Collections.shuffle(mHelperLib);
        }
        return mHelperLib.remove(0);
    }

    public String getAttrFieldString() {
        StringBuffer ret = new StringBuffer();
        for (AttributeCard c : mAttributeField) {
            ret.append(c.toString() + " ");
        }
        return ret.toString();
    }

    public ArrayList<String> getSpellFieldStrings() {
        ArrayList<String> ret = new ArrayList<String>();
        for (SpellCard c : mSpellField) {
            ret.add(c.toString());
        }
        return ret;
    }

    public AttributeCard acquire(String name, String target) {
        Player p = findPlayer(name);
        if (p == null) {
            return null;
        }
        for (AttributeCard c : mAttributeField) {
            if (c.toChar() == target.charAt(0) || c.getName().contains(target)) {
                mAttributeField.remove(c);
                p.gainAttrCard(c);
                return c;
            }
        }
        return null;
    }

    public AttributeCard recycle(String name, String target) {
        Player p = findPlayer(name);
        if (p == null) {
            return null;
        }
        for (AttributeCard c : mAttrConsumed) {
            if (c.toChar() == target.charAt(0) || c.getName().contains(target)) {
                mAttrConsumed.remove(c);
                p.gainAttrCard(c);
                return c;
            }
        }
        return null;
    }

    public AttributeCard giveAttr(String giver, String receiver, String card) {
        Player g = findPlayer(giver);
        if (g == null) {
            return null;
        }
        Player r = findPlayer(receiver);
        if (r == null) {
            return null;
        }
        AttributeCard c = g.discard(card);
        if (c == null) {
            return null;
        }
        r.gainAttrCard(c);
        return c;
    }

    public SpellCard giveSpell(String giver, String receiver, String card) {
        Player g = findPlayer(giver);
        if (g == null) {
            return null;
        }
        Player r = findPlayer(receiver);
        if (r == null) {
            return null;
        }
        SpellCard c = g.dispell(card);
        if (c == null) {
            return null;
        }
        r.gainSpellCardForced(c);
        return c;
    }

    public HelperCard giveHelper(String giver, String receiver) {
        Player g = findPlayer(giver);
        if (g == null) {
            return null;
        }
        Player r = findPlayer(receiver);
        if (r == null) {
            return null;
        }
        HelperCard c = g.consumeHelper();
        if (c == null) {
            return null;
        }
        r.gainHelperCard(c);
        return c;
    }

    public SpellCard getSpell(String name, String target) {
        Player p = findPlayer(name);
        if (p == null) {
            return null;
        }
        for (SpellCard c : mSpellField) {
            if (c.getName().contains(target)) {
                HashSet<AttributeCard> removal = p.gainSpellCard(c);
                if (removal != null) {
                    mSpellField.remove(c);
                    mAttrConsumed.addAll(removal);
                    changeSituation();
                    return c;
                }
            }
        }
        return null;
    }

    public SpellCard getSpellForced(String name, String target) {
        Player p = findPlayer(name);
        if (p == null) {
            return null;
        }
        for (SpellCard c : mSpellField) {
            if (c.getName().contains(target)) {
                p.gainSpellCardForced(c);
                mSpellField.remove(c);
                changeSituation();
                return c;
            }
        }
        return null;
    }

    public AttributeCard dealAttribute() {
        AttributeCard card = drawAttribute();
        mAttributeField.add(card);
        return card;
    }

    public SpellCard dealSpell() {
        SpellCard card = drawSpell();
        mSpellField.add(card);
        return card;
    }

    public Player findPlayer(String name) {
        for (Player p : mPlayers) {
            if (p.getName().equals(name)) {
                return p;
            }
        }
        return null;
    }

    public void nextTurn() {
        ++mTurn;
        if (mTurn >= mPlayers.size()) {
            mTurn = 0;
        }
    }

    public Player currentPlayer() {
        return mPlayers.get(mTurn);
    }

    public void changeSituation() {
        Collections.shuffle(mSituationLib);
        mSituationCard = mSituationLib.get(0);
    }

    public SituationCard getSituationCard() {
        return mSituationCard;
    }

    public AttributeCard discard(String name, String target) {
        Player p = findPlayer(name);
        if (p == null) {
            return null;
        }
        AttributeCard c = p.discard(target);
        if (c != null) {
            mAttrConsumed.add(c);
        }
        return c;
    }

    public AttributeCard draw(String name) {
        AttributeCard c = drawAttribute();
        findPlayer(name).gainAttrCard(c);
        return c;
    }

    public HelperCard getHelper(String name, String[] cmd) {
        Player p = findPlayer(name);
        AttributeCard c1 = p.discard(cmd[1]);
        if (c1 == null) {
            return null;
        }
        AttributeCard c2 = p.discard(cmd[2]);
        if (c2 == null) {
            p.gainAttrCard(c1);
            return null;
        }
        if (c1.getAttribute() == c2.getAttribute()) {
            p.gainAttrCard(c1);
            p.gainAttrCard(c2);
            return null;
        }
        mAttrConsumed.add(c1);
        mAttrConsumed.add(c2);
        HelperCard c = drawHelperCard();
        p.gainHelperCard(c);
        return c;
    }

    public HelperCard consumeHelper(String nick, String[] cmd) {
        Player p = findPlayer(nick);
        HelperCard c;
        if (cmd.length == 1) {
            c = p.consumeHelper();
        } else {
            c = p.consumeHelper(cmd[1]);
        }
        mHelperConsumed.add(c);
        return c;
    }

    public String getAttrConsumedString() {
        int[] a = new int[]{0, 0, 0, 0, 0};
        for (AttributeCard c : mAttrConsumed) {
            a[c.getAttribute()]++;
        }
        StringBuffer b = new StringBuffer();
        for (int i = 0; i < 5; ++i) {
            b.append(Card.ATTRIBUTES.charAt(i) + ": " + a[i] + "枚、");
        }
        return b.substring(0, b.length() - 1).toString();
    }

    public void eatHistory(String target) {
        if ("属性".equals(target)) {
            for (AttributeCard c : mAttributeField) {
                mAttrLib.add(mAttrLib.size() - 1, c);
            }
            mAttributeField.clear();
            for (int i = 0; i < 5; ++i) {
                mAttributeField.add(drawAttribute());
            }
        } else if ("スペル".equals(target)) {
            for (SpellCard c : mSpellField) {
                mSpellLib.add(mSpellLib.size() - 1, c);
            }
            mSpellField.clear();
            for (int i = 0; i < 4; ++i) {
                mSpellField.add(drawSpell());
            }
        }
    }

    public SpellCard returnSpell(String nick, String card) {
        Player g = findPlayer(nick);
        if (g == null) {
            return null;
        }
        SpellCard c = g.dispell(card);
        if (c == null) {
            return null;
        }
        mSpellLib.add(mSpellLib.size() - 1, c);
        return c;
    }
}
